#ifndef CAR_H
#define CAR_H

#include <vector>
#include <string>
#include <fstream>
#include <iostream>

// 订阅者模式抽象类
class Subject;

// 观察者抽象类（底盘作为观察者）
class Observer {
public:
    virtual void update(const std::string& obstacleStatus) = 0; // 非const：需要响应操作
    virtual ~Observer() = default;
};

// 主题抽象类（激光雷达作为主题）
class Subject {
private:
    std::vector<Observer*> observers;

public:
    void attach(Observer* observer); // 非const：修改订阅者列表
    void detach(Observer* observer); // 非const：修改订阅者列表
    void notify(const std::string& obstacleStatus); // 非const：触发通知
    virtual ~Subject() = default;
};

// 轮胎类
class Tire {
private:
    std::string type;
    std::string size;
public:
    Tire() = default;
    Tire(const std::string& type, const std::string& size) : type(type), size(size) {}
    std::string getType() const { return type; }
    std::string getSize() const { return size; }
    void setType(const std::string& type) { this->type = type; }
    void setSize(const std::string& size) { this->size = size; }
    void print() const {
        std::cout << "Tire[type=" << type << ", size=" << size << "]" << std::endl;
    }
    friend std::ostream& operator<<(std::ostream& os, const Tire& tire);
    friend std::istream& operator>>(std::istream& is, Tire& tire);
    void save(){
        std::ofstream outFile("tire_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<type<<"|"<<size<<std::endl;
            outFile.close();
            std::cout<<"轮胎信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存轮胎信息！"<<std::endl;
        }
    }
};

// 底盘类（继承观察者）
class Chassis : public Observer {
private:
    std::string id;
    std::string model;
    std::string wheelbase;
    std::string trackWidth;
    std::string minGroundClear;
    std::string minTurnRadius;
    std::string driveType;
    std::string maxRange;
    Tire tires[4];
public:
    Chassis() = default;
    Chassis(const std::string& id, const std::string& model, const std::string& wheelbase,
            const std::string& trackWidth, const std::string& minGroundClear, const std::string& minTurnRadius,
            const std::string& driveType, const std::string& maxRange, const Tire tires[4])
            : id(id), model(model), wheelbase(wheelbase), trackWidth(trackWidth),
            minGroundClear(minGroundClear), minTurnRadius(minTurnRadius),
            driveType(driveType), maxRange(maxRange) {
                for (int i = 0; i < 4; i++) {
                    this->tires[i] = tires[i];
                }
            }

    // 实现观察者更新方法（非const）
    void update(const std::string& obstacleStatus) override {
        std::cout << "\n【底盘响应】接收到障碍物状态：" << obstacleStatus << " → ";
        if (obstacleStatus == "前方") {
            std::cout << "执行后退操作。。。。" << std::endl;
        } else if (obstacleStatus == "左前方") {
            std::cout << "执行右转操作。。。。" << std::endl;
        } else if (obstacleStatus == "右前方") {
            std::cout << "执行左转操作。。。。" << std::endl;
        } else {
            std::cout << "无对应操作（状态异常）" << std::endl;
        }
    }

    // get/set方法
    std::string getId() const { return id; }
    std::string getModel() const { return model; }
    std::string getWheelbase() const { return wheelbase; }
    std::string getTrackWidth() const { return trackWidth; }
    std::string getMinGroundClear() const { return minGroundClear; }
    std::string getMinTurnRadius() const { return minTurnRadius; }
    std::string getDriveType() const { return driveType; }
    std::string getMaxRange() const { return maxRange; }

    void setId(const std::string& id) { this->id = id; }
    void setModel(const std::string& model) { this->model = model; }
    void setWheelbase(const std::string& wheelbase) { this->wheelbase = wheelbase; }
    void setTrackWidth(const std::string& trackWidth) { this->trackWidth = trackWidth; }
    void setMinGroundClear(const std::string& minGroundClear) { this->minGroundClear = minGroundClear; }
    void setMinTurnRadius(const std::string& minTurnRadius) { this->minTurnRadius = minTurnRadius; }
    void setDriveType(const std::string& driveType) { this->driveType = driveType; }
    void setMaxRange(const std::string& maxRange) { this->maxRange = maxRange; }
    Tire getTires(int index) const { return tires[index]; }
    void setTires(int index, const Tire& tire) { this->tires[index] = tire; }

    friend std::ostream& operator<<(std::ostream& os, const Chassis& chassis);
    friend std::istream& operator>>(std::istream& is, Chassis& chassis);

    void print() const {
        std::cout << "Chassis[id=" << id << ", model=" << model << ", wheelbase=" << wheelbase
            << ", trackWidth=" << trackWidth << ", minGroundClear=" << minGroundClear
            << ", minTurnRadius=" << minTurnRadius << ", driveType=" << driveType
            << ", maxRange=" << maxRange << "]" << std::endl;
        for (int i = 0; i < 4; i++) {
            std::cout << "  Tire " << (i + 1) << ": ";
            tires[i].print();
        }
    }
    void save(){
        std::ofstream outFile("chassis_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<id<<"|"<<model<<"|"<<wheelbase<<"|"<<trackWidth<<"|"
                   <<minGroundClear<<"|"<<minTurnRadius<<"|"<<driveType<<"|"
                   <<maxRange;
            for(int i=0;i<4;i++){
                tires[i].save();
            }
            outFile<<std::endl;
            outFile.close();
            std::cout<<"底盘信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存底盘信息！"<<std::endl;
        }
    }
};

// AGX套件类
class AGXKit {
private:
    std::string model;
    std::string aiPerformance;
    std::string cudaCores;
    std::string tensorCores;
    std::string vram;
    std::string storage;

public:
    AGXKit() = default;

    std::string getModel() const { return model; }
    void setModel(const std::string& model) { this->model = model; }
    std::string getAiPerformance() const { return aiPerformance; }
    void setAiPerformance(const std::string& aiPerformance) { this->aiPerformance = aiPerformance; }
    std::string getCudaCores() const { return cudaCores; }
    void setCudaCores(const std::string& cudaCores) { this->cudaCores = cudaCores; }
    std::string getTensorCores() const { return tensorCores; }
    void setTensorCores(const std::string& tensorCores) { this->tensorCores = tensorCores; }
    std::string getVram() const { return vram; }
    void setVram(const std::string& vram) { this->vram = vram; }
    std::string getStorage() const { return storage; }
    void setStorage(const std::string& storage) { this->storage = storage; }

    void print() const {
        std::cout << "AGXKit[model=" << model
                  << ", aiPerformance=" << aiPerformance
                  << ", cudaCores=" << cudaCores
                  << ", tensorCores=" << tensorCores
                  << ", vram=" << vram
                  << ", storage=" << storage
                  << "]" << std::endl;
    }

    void save(){
        std::ofstream outFile("agxkit_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<model<<"|"<<aiPerformance<<"|"<<cudaCores<<"|"
                   <<tensorCores<<"|"<<vram<<"|"<<storage<<std::endl;
            outFile.close();
            std::cout<<"AGX套件信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存AGX套件信息！"<<std::endl;
        }
    }
    friend std::ostream& operator<<(std::ostream& os, const AGXKit& agxKit);
    friend std::istream& operator>>(std::istream& is, AGXKit& agxKit);
};

// 双目摄像头类
class StereoCamera {
private:
    std::string model;
    std::string camModule;
    std::string rgbRes;
    std::string rgbFps;
    std::string fov;
    std::string depthFps;

public:
    StereoCamera() = default;

    std::string getModel() const { return model; }
    void setModel(const std::string& model) { this->model = model; }
    std::string getCamModule() const { return camModule; }
    void setCamModule(const std::string& camModule) { this->camModule = camModule; }
    std::string getRgbRes() const { return rgbRes; }
    void setRgbRes(const std::string& rgbRes) { this->rgbRes = rgbRes; }
    std::string getRgbFps() const { return rgbFps; }
    void setRgbFps(const std::string& rgbFps) { this->rgbFps = rgbFps; }
    std::string getFov() const { return fov; }
    void setFov(const std::string& fov) { this->fov = fov; }
    std::string getDepthFps() const { return depthFps; }
    void setDepthFps(const std::string& depthFps) { this->depthFps = depthFps; }

    void print() const {
        std::cout << "StereoCamera[model=" << model
                  << ", camModule=" << camModule
                  << ", rgbRes=" << rgbRes
                  << ", rgbFps=" << rgbFps
                  << ", fov=" << fov
                  << ", depthFps=" << depthFps
                  << "]" << std::endl;
    }

    void save(){
        std::ofstream outFile("stereocam_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<model<<"|"<<camModule<<"|"<<rgbRes<<"|"
                   <<rgbFps<<"|"<<fov<<"|"<<depthFps<<std::endl;
            outFile.close();
            std::cout<<"双目双目摄像头信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存双目摄像头信息！"<<std::endl;
        }
    }
    friend std::ostream& operator<<(std::ostream& os, const StereoCamera& stereoCam);
    friend std::istream& operator>>(std::istream& is, StereoCamera& stereoCam);
};

// 多线激光雷达类（继承主题）
class LiDAR : public Subject {
private:
    std::string model;
    std::string lines;
    std::string testRange;
    std::string power;
    std::string obstacleStatus;

public:
    LiDAR() = default;

    // 更新障碍物状态并通知订阅者（非const）
    void updateObstacleStatus(const std::string& status) {
        this->obstacleStatus = status;
        std::cout << "\n【激光雷达】检测到障碍物：" << obstacleStatus << "，正在通知订阅者" << std::endl;
        this->notify(obstacleStatus);
    }

    // get/set方法
    std::string getModel() const { return model; }
    void setModel(const std::string& model) { this->model = model; }
    std::string getLines() const { return lines; }
    void setLines(const std::string& lines) { this->lines = lines; }
    std::string getTestRange() const { return testRange; }
    void setTestRange(const std::string& testRange) { this->testRange = testRange; }
    std::string getPower() const { return power; }
    void setPower(const std::string& power) { this->power = power; }
    std::string getObstacleStatus() const { return obstacleStatus; }
    void setObstacleStatus(const std::string& status) { this->obstacleStatus = status; }

    void print() const {
        std::cout << "LiDAR[model=" << model
                  << ", lines=" << lines
                  << ", testRange=" << testRange
                  << ", power=" << power
                  << ", 障碍物状态=" << obstacleStatus
                  << "]" << std::endl;
    }

    void save(){
        std::ofstream outFile("lidar_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<model<<"|"<<lines<<"|"<<testRange<<"|"<<power<<"|"<<obstacleStatus<<std::endl;
            outFile.close();
            std::cout<<"多线激光雷达信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存多线激光雷达信息！"<<std::endl;
        }
    }
    friend std::ostream& operator<<(std::ostream& os, const LiDAR& lidar);
    friend std::istream& operator>>(std::istream& is, LiDAR& lidar);
};

// 9轴陀螺仪类
class Gyroscope {
private:
    std::string model;
    std::string manufacturer;

public:
    Gyroscope() = default;

    std::string getModel() const { return model; }
    void setModel(const std::string& model) { this->model = model; }
    std::string getManufacturer() const { return manufacturer; }
    void setManufacturer(const std::string& manufacturer) { this->manufacturer = manufacturer; }

    void print() const {
        std::cout << "Gyroscope[model=" << model
                  << ", manufacturer=" << manufacturer
                  << "]" << std::endl;
    }

    void save(){
        std::ofstream outFile("gyroscope_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<model<<"|"<<manufacturer<<std::endl;
            outFile.close();
            std::cout<<"9轴陀螺仪信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存9轴陀螺仪信息！"<<std::endl;
        }
    }

    friend std::ostream& operator<<(std::ostream& os, const Gyroscope& gyro);
    friend std::istream& operator>>(std::istream& is, Gyroscope& gyro);
};

// 液晶显示屏类
class LCDScreen {
private:
    std::string size;
    std::string model;

public:
    LCDScreen() = default;

    std::string getSize() const { return size; }
    void setSize(const std::string& size) { this->size = size; }
    std::string getModel() const { return model; }
    void setModel(const std::string& model) { this->model = model; }

    void print() const {
        std::cout << "LCDScreen[size=" << size
                  << ", model=" << model
                  << "]" << std::endl;
    }

    void save(){
        std::ofstream outFile("lcdscreen_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<size<<"|"<<model<<std::endl;
            outFile.close();
            std::cout<<"液晶显示屏信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存液晶显示屏信息！"<<std::endl;
        }
    }
    friend std::ostream& operator<<(std::ostream& os, const LCDScreen& lcd);
    friend std::istream& operator>>(std::istream& is, LCDScreen& lcd);
};

// 电池类
class Bettery {
private:
    std::string params;
    std::string outputVolt;
    std::string chargeTime;

public:
    Bettery() = default;

    std::string getParams() const { return params; }
    void setParams(const std::string& params) { this->params = params; }
    std::string getOutputVolt() const { return outputVolt; }
    void setOutputVolt(const std::string& outputVolt) { this->outputVolt = outputVolt; }
    std::string getChargeTime() const { return chargeTime; }
    void setChargeTime(const std::string& chargeTime) { this->chargeTime = chargeTime; }

    void print() const {
        std::cout << "Bettery[params=" << params
                  << ", outputVolt=" << outputVolt
                  << ", chargeTime=" << chargeTime
                  << "]" << std::endl;
    }
    void save(){
        std::ofstream outFile("bettery_info.txt",std::ios::app);
        if(outFile.is_open()){
            outFile<<params<<"|"<<outputVolt<<"|"<<chargeTime<<std::endl;
            outFile.close();
            std::cout<<"电池信息保存成功！"<<std::endl;
        }else{
            std::cerr<<"无法打开文件保存电池信息！"<<std::endl;
        }
    }

    friend std::ostream& operator<<(std::ostream& os, const Bettery& battery);
    friend std::istream& operator>>(std::istream& is, Bettery& battery);
};

// 学生类
class Student {
private:
    std::string id;
    std::string name;

public:
    Student() = default;
    Student(const std::string& id, const std::string& name) : id(id), name(name) {}

    std::string getId() const { return id; }
    void setId(const std::string& id) { this->id = id; }

    std::string getName() const { return name; }
    void setName(const std::string& name) { this->name = name; }

    void print() const {
        std::cout << "Student[id=" << id
                  << ", name=" << name
                  << "]" << std::endl;
    }

    friend std::ostream& operator<<(std::ostream& os, const Student& student);
    friend std::istream& operator>>(std::istream& is, Student& student);
};

// 小车类
class Car {
private:
    std::string carId;
    Chassis chassis;
    AGXKit agxKit;
    StereoCamera stereoCamera;
    LiDAR lidar;
    Gyroscope gyroscope;
    LCDScreen lcdScreen;
    Bettery bettery;
    Student student;
    bool isAssignedStudent = false;

    void initDefaultComponents();

public:
    Car();
    Car(const std::string& carId);

    void setCarId(const std::string& carId);
    void assignStudent(const Student& student);
    void setChassis(const Chassis& chassis);
    void setAGXKit(const AGXKit& agxKit);
    void setStereoCamera(const StereoCamera& stereoCamera);
    void setLiDAR(const LiDAR& lidar);
    void setGyroscope(const Gyroscope& gyroscope);
    void setLCDScreen(const LCDScreen& lcdScreen);
    void setBattery(const Bettery& bettery);

    bool getIsAssignedStudent() const;
    std::string getCarId() const;
    Student getStudent() const;
    
    // 关键修复：重载const和非const版本的getter
    Chassis& getChassis();
    const Chassis& getChassis() const;  // const版本，供const成员函数调用
    
    AGXKit getAGXKit() const;
    StereoCamera getStereoCamera() const;
    
    LiDAR& getLiDAR();
    const LiDAR& getLiDAR() const;      // const版本，供const成员函数调用
    
    Gyroscope getGyroscope() const;
    LCDScreen getLCDScreen() const;
    Bettery getBettery() const;

    void displayCarInfo() const;

    void serialize(std::ostream& os) const;
    void deserialize(std::istream& is);

    void print() const {
        std::cout << "Car[carId=" << carId
                  << ", isAssignedStudent=" << (isAssignedStudent ? "true" : "false")
                  << "]" << std::endl;
        chassis.print();
        agxKit.print();
        stereoCamera.print();
        lidar.print();
        gyroscope.print();
        lcdScreen.print();
        bettery.print();
        student.print();
    }

    static bool saveCarsToFile(const std::vector<Car>& cars, const std::string& filename);
    static bool loadCarsFromFile(std::vector<Car>& cars, const std::string& filename);
};

#endif // CAR_H